<?php

class FlexiHash
{
    private $serverList = [];
    private $isSorted   = false;

    private function getIntHash($key)
    {
        $md5  = substr(md5($key), 0, 8);
        $seed = 31;
        $hash = 0;

        for ($i = 0; $i < 8; $i++) {
            $hash = $hash * $seed + ord($md5{$i});
            $i++;
        }
        return $hash & 0x7FFFFFFF;
    }

    /**
     * addServer
     */
    public function addServer($server)
    {
        $hash = $this->getIntHash($server);
        if (!isset($this->serverList[$hash])) {
            $this->serverList[$hash] = $server;
        }
        $this->isSorted = false;
        return true;
    }

    /**
     * removeServer
     */
    public function removeServer($server)
    {
        $hash = $this->getIntHash($server);
        if (isest($this->serverList[$hash])) {
            unset($this->serverList[$hash]);
        }
        $this->isSorted = false;
        return true;
    }

    /**
     * loolup
     */
    public function lookup($key)
    {
        $hash = $this->getIntHash($key);
        if (!$this->isSorted) {
            krsort($this->serverList, SORT_NUMERIC);
            $this->isSorted = true;
        }
        foreach ($this->serverList as $pos => $server) {
            if ($hash >= $pos) {
                return $server;
            }
        }
        $server = array_slice($this->serverList, 0, 1);
        return $server[0];
    }

}
$hserver = new FlexiHash();
$hserver->addServer("192.168.1.1");
$hserver->addServer("192.168.1.2");
$hserver->addServer("192.168.1.3");
$hserver->addServer("192.168.1.4");
$hserver->addServer("192.168.1.5");
$hserver->lookup('key1');
